//
//  PDFToImageTool.m
//  TQLWhiteBoard
//
//  Created by tql on 2020/9/1.
//  Copyright © 2020 tqlLW. All rights reserved.
//

#import "PDFToImageTool.h"
#import <CoreGraphics/CoreGraphics.h>

#define     DebugMethod()  NSLog(@"%s",__func__)
@interface PDFToImageTool()
{
  __block  CGPDFDocumentRef thePDFDocRef;
     NSInteger pageCount ;
}
@end

@implementation PDFToImageTool





CGPDFDocumentRef CGPDFDocumentCreateUsingUrl(CFURLRef theURL, NSString *password)
{
    CGPDFDocumentRef thePDFDocRef = NULL; // CGPDFDocument

    if (theURL != NULL) // Check for non-NULL CFURLRef
    {
        thePDFDocRef = CGPDFDocumentCreateWithURL(theURL);

        if (thePDFDocRef != NULL) // Check for non-NULL CGPDFDocumentRef
        {
            if (CGPDFDocumentIsEncrypted(thePDFDocRef) == TRUE) // Encrypted
            {
                // Try a blank password first, per Apple's Quartz PDF example

                if (CGPDFDocumentUnlockWithPassword(thePDFDocRef, "") == FALSE)
                {
                    // Nope, now let's try the provided password to unlock the PDF

                    if ((password != nil) && (password.length > 0)) // Not blank?
                    {
                        char text[128]; // char array buffer for the string conversion

                        [password getCString:text maxLength:126 encoding:NSUTF8StringEncoding];

                        if (CGPDFDocumentUnlockWithPassword(thePDFDocRef, text) == FALSE) // Log failure
                        {
                            #ifdef DEBUG
                                NSLog(@"CGPDFDocumentCreateUsingUrl: Unable to unlock [%@] with [%@]", theURL, password);
                            #endif
                        }
                    }
                }

                if (CGPDFDocumentIsUnlocked(thePDFDocRef) == FALSE) // Cleanup unlock failure
                {
                    CGPDFDocumentRelease(thePDFDocRef), thePDFDocRef = NULL;
                }
            }
        }
    }
    else // Log an error diagnostic
    {
        #ifdef DEBUG
            NSLog(@"CGPDFDocumentCreateUsingUrl: theURL == NULL");
        #endif
    }

    return thePDFDocRef;
}

- (void)PdfToImageWithPDFFileUrl: (NSString *) PdfFileUrl
                        progress: (void (^)(CGFloat value)) progress
                      completion: (void (^)(NSArray * images)) completion{
    DebugMethod();
    CFURLRef docURLRef = (__bridge CFURLRef)[NSURL fileURLWithPath: PdfFileUrl]; // CFURLRef from NSURL

     thePDFDocRef = CGPDFDocumentCreateUsingUrl(docURLRef,nil);
    if (thePDFDocRef != NULL) // Get the total number of pages in the document
    {
         pageCount = CGPDFDocumentGetNumberOfPages(thePDFDocRef);
        
        
        
//        CGPDFDocumentRelease(thePDFDocRef); // Cleanup//处理完后掉用。
//        NSLog(@"%@",_p)
        
        if (pageCount>0) {
            
            dispatch_queue_t serialQueue = dispatch_queue_create(  "serialQueue" , DISPATCH_QUEUE_SERIAL);
            
            dispatch_async(serialQueue, ^{
               
                dispatch_semaphore_t semap = dispatch_semaphore_create(0);
                
                NSMutableArray *returnArray = [NSMutableArray array];
                for (int i =0; i< pageCount; i++) {

                    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.01 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
                 
                
                        if (progress) {
                            dispatch_async(dispatch_get_main_queue(), ^{
                                progress(i/(pageCount*1.0));
                            });
                        }
                        
                        if (1) {
                          CGPDFPageRef page;
                            page = CGPDFDocumentGetPage (thePDFDocRef,i);

                            UIImage *image = [self getUIImageFromPDFPage:i pdfPage:page];
                            if (image) {
                                [returnArray addObject:image];
                            }
                            
                        }else{
                            
                            
                            CGImageRef imgRef = PDFPageToCGImage(i, thePDFDocRef);
                          
                            if (imgRef) {
                                UIImage *image = [UIImage imageWithCGImage:imgRef];
                                
                                [returnArray addObject:image];
                            }
                        }
                        
                        
                        dispatch_semaphore_signal(semap );
                    });
                    dispatch_semaphore_wait(semap, DISPATCH_TIME_FOREVER);

                  
                }
                
                dispatch_async(dispatch_get_main_queue(), ^{
                    CGPDFDocumentRelease(thePDFDocRef);
                    completion(returnArray);
                });
            });
            
           
            
            
        }else{
             CGPDFDocumentRelease(thePDFDocRef);
            completion(nil);
        }
        
    }else{
         CGPDFDocumentRelease(thePDFDocRef);
        completion(nil);
    }
    
    
}
CGImageRef PDFPageToCGImage(size_t pageNumber, CGPDFDocumentRef document)
{
    
    CGPDFPageRef page;
    
    CGRect pageSize;
    
    CGContextRef outContext;
    
    CGImageRef ThePDFImage;
    
    CGAffineTransform ctm;
    
    page = CGPDFDocumentGetPage (document,pageNumber);
    
    if(page)
        
    {
        
        pageSize=CGPDFPageGetBoxRect(page,kCGPDFMediaBox);
        
        outContext= CreateARGBBitmapContext (pageSize.size.width, pageSize.size.height);
        
        if(outContext)
            
        {
            
            CGContextDrawPDFPage(outContext,page);
            
            ThePDFImage= CGBitmapContextCreateImage(outContext);
            
            CFRelease(outContext);
            
            return ThePDFImage;
            
        }
        
    }
    
    return NULL;
    
}


CGContextRef CreateARGBBitmapContext (size_t pixelsWide, size_t pixelsHigh)

{
    
    CGContextRef   context = NULL;
    
    CGColorSpaceRef colorSpace;
    
    void *        bitmapData;
    
    int          bitmapByteCount;
    
    int          bitmapBytesPerRow;
    
    // Get image width, height. We’ll use the entire image.
    
    // size_t pixelsWide = CGImageGetWidth(inImage);
    
    // size_t pixelsHigh = CGImageGetHeight(inImage);
    
    // Declare the number of bytes perrow. Each pixel in the bitmap in this
    
    // example is represented by 4bytes; 8 bits each of red, green, blue, and
    
    // alpha.
    
    bitmapBytesPerRow  = (pixelsWide * 4);
    
    bitmapByteCount    = (bitmapBytesPerRow *pixelsHigh);
    
    // Use the generic RGB colorspace.
    
    colorSpace =CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);
    
    if(colorSpace == NULL)
        
    {
        
        fprintf(stderr, "Error allocating colorspace\n");
        
        return NULL;
        
    }
    
    // Allocate memory for image data.This is the destination in memory
    
    // where any drawing to the bitmapcontext will be rendered.
    
    bitmapData = malloc( bitmapByteCount );
    
    if(bitmapData == NULL)
        
    {
        
        fprintf (stderr, "Memory notallocated!");
        
        CGColorSpaceRelease(colorSpace );
        
        return NULL;
        
    }
    
    // Create the bitmap context. Wewant pre-multiplied ARGB, 8-bits
    
    // per component. Regardless ofwhat the source image format is
    
    // (CMYK, Grayscale, and so on) itwill be converted over to the format
    
    // specified here byCGBitmapContextCreate.
    
    context = CGBitmapContextCreate(bitmapData,
                                    
                                    pixelsWide,
                                    
                                    pixelsHigh,
                                    
                                    8,     // bits per component
                                    
                                    bitmapBytesPerRow,
                                    
                                    colorSpace,
                                    
                                    kCGImageAlphaPremultipliedFirst);
    
    if(context == NULL)
        
    {
        
        free (bitmapData);
        
        fprintf (stderr, "Context not created!");
        
    }
    
    // Make sure and release colorspacebefore returning
    
    CGColorSpaceRelease( colorSpace);
    
    return context;
    
}

-(UIImage *)getUIImageFromPDFPage:(int)page_number pdfPage: (CGPDFPageRef)ppage
{
    CGRect pageRect = CGPDFPageGetBoxRect(ppage, kCGPDFMediaBox);
    
    NSLog(@"w=%f,y=%f",pageRect.size.width,pageRect.origin.y);
    pageRect.origin = CGPointZero;
    //开启图片绘制 上下文
    UIGraphicsBeginImageContext(pageRect.size);
    CGContextRef context = UIGraphicsGetCurrentContext();

    // 设置白色背景
    CGContextSetRGBFillColor(context, 1.0,1.0,1.0,1.0);
    CGContextFillRect(context,pageRect);
    CGContextSaveGState(context);

    //进行翻转
    CGContextTranslateCTM(context, 0.0, pageRect.size.height);
    CGContextScaleCTM(context, 1.0, -1.0);
    CGContextConcatCTM(context, CGPDFPageGetDrawingTransform(ppage, kCGPDFMediaBox, pageRect, 0,true));
    CGContextDrawPDFPage(context, ppage);
    CGContextRestoreGState(context);
    UIImage *pdfImage = UIGraphicsGetImageFromCurrentImageContext();

    UIGraphicsEndImageContext();

    return pdfImage;

}


@end
